#ifndef USERINFO_H
#define USERINFO_H

#include "Game/GameDefine.h"
#include "Game/SocketDefine.h"

#include "_Global/Socket/ClientSocket.h"
#include "_Global/GlobalClass.h"

#include <QObject>
#include <QList>
#include <QDebug>

#include <QUuid>

//游戏服务器信息列表
class _GameServerInfo: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name)


public:
    explicit _GameServerInfo(QObject *parent = nullptr): QObject(parent)
    {
        m_nServerID = -1;
        m_strName = "";
        m_strIP = "";
        m_unPort = 0;
        m_strKey = "";
    }

public:
    QString name() const
    {
        return m_strName;
    }


public:
    //游戏服务器状态
    quint32 m_nServerID;    //服务器id
    QString m_strName;
    QString m_strIP;
    quint16 m_unPort;
    QString m_strKey;
};



class Sqlite;
class TcpSocket;

//用户数据
class UserInfo: public QObject
{
    Q_OBJECT
    Q_ENUMS(_ClientStatus)
    Q_FLAGS(_TestFlag)
    Q_PROPERTY(quint32 userID READ getUserID)
    Q_PROPERTY(quint32 userGameID READ getUserGameID)
    Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged)
    Q_PROPERTY(QString nickName READ nickName WRITE setNickName NOTIFY nickNameChanged)
    Q_PROPERTY(qint16 sex READ sex WRITE setSex NOTIFY sexChanged)
    Q_PROPERTY(int scoreCount READ scoreCount WRITE setScoreCount NOTIFY scoreCountChanged) //积分

    Q_PROPERTY(QVariantMap gameServerInfo READ gameServerInfo)  //ServerInfo列表
    Q_PROPERTY(qint32 serverID READ serverID)  //当前ServerID
    Q_PROPERTY(QString serverName READ serverName)  //当前ServerName

public:
    //客户端的登录状态
    enum _ClientStatus  //注意：m_pGameSocket接受的状态设置全部需要修改！
    {
        Client_IsLoginOut = 0,       //登出状态 [客户端]
        Client_IsRegisteringInfoServer,         //正在注册信息服务器 [客户端]
        Client_IsLoginingInfoServer,            //正在登录信息服务器 [客户端]
        Client_IsLoginedInfoServer,             //已经登录信息服务器

        Client_IsRegisteringGameServer,         //正在注册游戏服务器 [客户端]
        Client_IsLoginingGameServer,            //正在登录游戏服务器 [客户端]
        Client_IsLoginedGameServer,             //已经登录游戏服务器
    };

    enum _TestFlag
    {
        Flag1 = 0,
        Flag2
    };

    //登录信息
    struct _LoginInfo
    {
        _ClientStatus m_ClientStatus;       //登录状态
        quint32 m_unID;         //客户id(数据库的id号)//void *m_id;
        //qint32 m_nSocketID;    //客户SocketID(服务器保存的客户id，唯一)
        QString m_strUserName;
        QString m_strNickName;
        QString m_strPassword;
        qint16 m_nClientType;

        _LoginInfo()
        {
            m_ClientStatus = Client_IsLoginOut;
            m_unID = 0;
            //m_nSocketID = 0;
            m_strUserName = "";
            m_strNickName = "";
            m_strPassword = "";

//客户端类型
#if defined(Q_OS_WIN32)         //win
            m_nClientType = 1;
#elif defined(Q_OS_ANDROID)     //android
            m_nClientType = 2;
#elif defined(Q_OS_MACOS)
            m_nClientType = 3;
#elif defined(Q_OS_IOS)
            m_nClientType = 4;
#elif defined(Q_OS_LINUX)       //linux,必须在Q_OS_ANDROID之后,因为Android环境会即将Linux也定义
            m_nClientType = 5;
#else
            m_nClientType = -1;
#endif
        }
    }m_LoginInfo;



//游戏服务器 用户数据
    //道具
    struct _GameServerUserInfo
    {
        _GameServerUserInfo()
        {
            unUserGameID = 0;
            strNickName = "";
            nSex = -1;
            nScoreCount = 0;
        }

        quint32 unUserGameID;
        QString strNickName;     //服务器昵称
        qint16 nSex;
        qint32 nScoreCount;        //服务器金币总数
        QVariant vExtraData;
        //ItemsInfo m_ItemsInfo;

    }m_GameServerUserInfo;


signals:
    void s_loginStatus(int code);   //登录状态.code:-1/-2(数据库错误);0(登录成功);1(没有注册);2(密码错误);-100(网络错误)
    void s_regStatus(int code);     //注册状态.code:0(成功);1(用户名重复)-1~-3(各种错误)
    void s_gameServerInfoStatus(int code);     //游戏服务器状态.code:0(成功);-100(选择游戏服务器错误);<0(获取游戏服务器的各种错误)
    void s_loginGameServerStatus(int code);   //登录游戏服务器状态.code:0(成功);1(没有注册);<0(各种错误)
    void s_regGameServerStatus(int code);     //注册游戏昵称帐户;1(已有人注册),2(长度不符合),3(含有禁词);<0(各种错误)
    //void s_choiceGameServerStatus(int code);  //选择服务器成功,next为-1是出错，1是需要注册昵称，为0 登录/注册 成功


//给GameManager的
    void s_SendCodeDataToServer(TcpSocket* pSocket,QByteArray ba);


//属性信号:
    void scoreCountChanged(int newValue);
    void nickNameChanged(QString newValue);
    void userNameChanged(QString newValue);
    void sexChanged(int newValue);



public:
    explicit UserInfo(QObject *parent = nullptr): QObject(parent)
    {
        m_pInfoSocket = nullptr;
        m_pGameSocket = nullptr;
        m_pSqliteDB = nullptr;
        m_nGameServerId = -1;
    }
    virtual ~UserInfo()
    {
        clearUserInfo();
    }


public:
    //bool loadUserInfo();    //从服务器读取用户信息,m_TempDB
    //bool updateUserScoreInfo();  //更新用户金币,m_TempDB

    //发送注册或登录信息
    //bool sendUserInfoToServer();
    //bool sendUserInfoToLocalTest(); //本地测试


    void clearUserInfo()
    {
        m_LoginInfo.m_ClientStatus = Client_IsLoginOut;
        m_LoginInfo.m_unID = 0;
        //m_nSocketID = 0;
        m_LoginInfo.m_strUserName = "";
        m_LoginInfo.m_strNickName = "";
        m_LoginInfo.m_strPassword = "";
        //m_LoginInfo.m_nClientType = 0;
        clearGameServersInfo();
        clearGameUserInfo();
    }

    //U.清空 游戏服务器信息
    void clearGameServersInfo()
    {
        QVariantMap::const_iterator ii;
        for(ii = m_mapGameServerInfo.constBegin(); ii != m_mapGameServerInfo.constEnd(); ii++)
            delete (*ii).value<_GameServerInfo*>();


        //qDeleteAll(m_mapGameServerInfo);
        m_mapGameServerInfo.clear();
    }

    void clearGameUserInfo()
    {
        m_GameServerUserInfo.unUserGameID = 0;
        m_GameServerUserInfo.strNickName = "";
        m_GameServerUserInfo.nSex = -1;
        m_GameServerUserInfo.nScoreCount = 0;
        m_GameServerUserInfo.vExtraData.clear();
    }


public slots:
    //登录/注册
    bool sl_qml_UserLogin(QVariant param);
    bool sl_qml_UserReg(QVariant param);
    bool sl_qml_GameUserReg(QVariant param); //用户 向注册游戏服务器 注册信息

    bool sl_qml_ChoiceGameServer(int gameServerID);

    int loadGameUserInfo()
    {
        _GameServerInfo* pGameServerInfo = m_mapGameServerInfo.value(QString::number(m_nGameServerId),QVariant::fromValue(nullptr))
                .value<_GameServerInfo*>();

        if(pGameServerInfo == nullptr)
            return false;

        m_LoginInfo.m_ClientStatus = Client_IsLoginingGameServer;

        m_pGameSocket->sendData() << (qint16)GAME_SERVER_REQUEST
                                  << (qint16)GAME_SERVER_CLIENT
                                  << (qint16)GAME_SERVER_CLIENT_GAMEUSERINFO
                                  << m_LoginInfo.m_unID
                                  << m_LoginInfo.m_strUserName
                                  << serverID()
                                  << pGameServerInfo->m_strKey
                                  << m_LoginInfo.m_nClientType
                                  << _Game_Version_
                                     ;
        m_pGameSocket->send(TRANSMIT_CLIENT_TYPE, true);

        qDebug()<<"[UserInfo]获取GameUserInfo中...";
        return 0;
    }

    bool updateGameUserScoreInfo(qint16 achieve, qint32 score)
    {
        QByteArray ba;
        QDataStream out(&ba,QIODevice::WriteOnly);
        out << (qint16)GAME_SERVER_REQUEST
            << (qint16)GAME_SERVER_CLIENT
            << (qint16)GAME_SERVER_CLIENT_UPDATESCORE
               //<<userGameID()
            << achieve
            << score;
        emit s_SendCodeDataToServer(m_pGameSocket,ba);

        setScoreCount(scoreCount() + score);

        return true;
    }

//qml直接调用:
public slots:
    QString sl_getServerName(qint32 serverid)
    {
        //if(m_GameServerIndex < 0 || m_mapGameServerInfo.count() <= m_GameServerIndex)
        //    return "";
        //return ((_GameServerInfo*)(m_mapGameServerInfo.value(serverid)))->name();
        _GameServerInfo* p = m_mapGameServerInfo.value(QString::number(serverid),QVariant::fromValue(nullptr))
                .value<_GameServerInfo*>();
        if(p == nullptr)
            return "";
        else
            return p->name();
    }

    //根据分数查询等级
    QVariantMap sl_getUserLevelInfo(int score);



protected:
    bool checkBadWord(QString word);    //检查词汇


//属性:
public:
    quint32 getUserID() const
    {
        return m_LoginInfo.m_unID;
    }
    quint32 getUserGameID() const
    {
        return m_GameServerUserInfo.unUserGameID;
    }

    QString userName() const
    {
        return m_LoginInfo.m_strUserName;
    }
    void setUserName(QString newValue)
    {
        if(m_LoginInfo.m_strUserName != newValue)
        {
            m_LoginInfo.m_strUserName = newValue;
            emit userNameChanged(newValue);
        }
    }
    QString nickName() const
    {
        return m_LoginInfo.m_strNickName;
    }
    void setNickName(QString newValue)
    {
        if(m_LoginInfo.m_strNickName != newValue)
        {
            m_LoginInfo.m_strNickName = newValue;
            emit nickNameChanged(newValue);
        }
    }
    qint16 sex() const
    {
        return m_GameServerUserInfo.nSex;
    }
    void setSex(qint16 newValue)
    {
        if(m_GameServerUserInfo.nSex != newValue)
        {
            m_GameServerUserInfo.nSex = newValue;
            emit sexChanged(newValue);
        }
    }


    qint32 scoreCount() const
    {
        return m_GameServerUserInfo.nScoreCount;
    }
    void setScoreCount(qint32 n)
    {
        if(m_GameServerUserInfo.nScoreCount != n)
        {
            m_GameServerUserInfo.nScoreCount = n;
            emit scoreCountChanged(n);
        }
    }


    QVariantMap gameServerInfo() const
    {
        return m_mapGameServerInfo;
    }

    qint32 serverID() const
    {
        //if(m_GameServerIndex < 0 || m_mapGameServerInfo.count() <= m_GameServerIndex)
        //    return 0;
        //return ((_GameServerInfo*)(m_mapGameServerInfo.value(m_nGameServerId)))->m_nServerID;
        return m_nGameServerId;
    }
    QString serverName()
    {
        return sl_getServerName(m_nGameServerId);
    }

//框架
public:
    TcpSocket*  m_pInfoSocket;        //InfoServerSocket
    TcpSocket*  m_pGameSocket;        //GameInfoServerSocket
    Sqlite*     m_pSqliteDB;         //本地数据库配置指针,由GameManager初始化

//游戏数据
public:
    QVariantMap m_mapGameServerInfo;   //游戏服务器信息列表(ID对应GameServerInfo指针)
    qint32      m_nGameServerId;      //用户选择的游戏信息服务器的ID
};


#endif // USERINFO_H
